package com.java.simple.jerrymouse;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author zhoujunlin
 * @date 2022年08月07日 17:56
 * @desc
 */
@Slf4j(topic = "c.JerryMouseApp")
public class JerryMouseApp {

    private final ExecutorService executorService = new ThreadPoolExecutor(8, 16,
            60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));

    private final byte[] LINE_BYTES = System.getProperty("line.separator").getBytes();

    public void start() {
        try (ServerSocket serverSocket = new ServerSocket(80, 50, InetAddress.getByName("127.0.0.1"))) {
            while (!executorService.isShutdown()) {
                try {
                    Socket accept = serverSocket.accept();
                    executorService.execute(() -> {
                        handle(accept);
                    });
                } catch (RejectedExecutionException e) {
                    if (!executorService.isShutdown()) {

                    }
                }
            }
        } catch (IOException e) {
            log.error("server socket error,", e);
        }
    }

    private void handle(Socket socket) {
        try {
            dispatch(socket);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void dispatch(Socket socket) throws IOException {
        MyHttpRequest myHttpRequest = new MyHttpRequest(socket);
        MyHttpResponse myHttpResponse = new MyHttpResponse(socket);
        String requestURI = myHttpRequest.getRequestURI();
        if (Objects.isNull(requestURI)) {
            return;
        }
        if (requestURI.equals("/")) {
            index(myHttpResponse.getOutputStream());
        } else {
            _404(myHttpResponse.getOutputStream());
        }
    }

    private void _404(OutputStream outputStream) throws IOException {
        outputStream.write("HTTP/1.1 404 NOT FOUND".getBytes());
        outputStream.write(LINE_BYTES);
        outputStream.write("Content-Type: application/json;charset=utf-8".getBytes());
        outputStream.write(LINE_BYTES);
        String html = "{\"error\":\"NOT FOUND\"}";
        byte[] bytes = html.getBytes(StandardCharsets.UTF_8);
        outputStream.write(("Content-Length: " + bytes.length).getBytes());
        outputStream.write(LINE_BYTES);
        outputStream.flush();
        outputStream.write(LINE_BYTES);
        outputStream.write(bytes);
        outputStream.flush();
    }

    private void index(OutputStream outputStream) throws IOException {
        outputStream.write("HTTP/1.1 200 OK".getBytes());
        outputStream.write(LINE_BYTES);
        outputStream.write("Content-type: text/html;charset=utf-8".getBytes());
        outputStream.write(LINE_BYTES);
        String html = "<html>" +
                "<body>" +
                "<h1>hello jerry mouse</h1>" +
                "</body>" +
                "</html>";
        byte[] bytes = html.getBytes(StandardCharsets.UTF_8);
        outputStream.write(("Content-Length: " + bytes.length).getBytes());
        outputStream.write(LINE_BYTES);
        outputStream.flush();
        outputStream.write(LINE_BYTES);
        outputStream.write(bytes);
        outputStream.flush();
    }

    public static void main(String[] args) {
        new JerryMouseApp().start();
    }

}
